package com.example.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.admin.common.exception.BusinessException;
import com.example.admin.entity.SysMenu;
import com.example.admin.entity.SysRoleMenu;
import com.example.admin.mapper.SysMenuMapper;
import com.example.admin.mapper.SysRoleMenuMapper;
import com.example.admin.service.MenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements MenuService {
    
    @Autowired
    private SysMenuMapper menuMapper;
    
    @Autowired
    private SysRoleMenuMapper roleMenuMapper;
    
    @Override
    public List<SysMenu> getMenuTree() {
        // 获取所有菜单
        List<SysMenu> allMenus = menuMapper.selectList(
            new LambdaQueryWrapper<SysMenu>()
                .orderByAsc(SysMenu::getSort)
        );
        
        // 构建树形结构
        return buildTree(allMenus);
    }
    
    @Override
    public List<SysMenu> getUserMenus(Long userId) {
        // 获取用户的菜单列表
        List<SysMenu> userMenus = menuMapper.selectByUserId(userId);
        
        // 构建树形结构
        return buildTree(userMenus);
    }
    
    private List<SysMenu> buildTree(List<SysMenu> menus) {
        // 按父ID分组
        Map<Long, List<SysMenu>> childrenMap = menus.stream()
            .collect(Collectors.groupingBy(SysMenu::getParentId));
            
        // 设置子菜单
        menus.forEach(menu -> menu.setChildren(childrenMap.get(menu.getId())));
        
        // 返回顶级菜单
        return menus.stream()
            .filter(menu -> menu.getParentId() == 0)
            .collect(Collectors.toList());
    }

    @Override
    public List<Long> getRoleMenuIds(Long roleId) {
        return roleMenuMapper.selectMenuIdsByRoleId(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRoleMenus(Long roleId, List<Long> menuIds) {
        // 先删除原有关联
        roleMenuMapper.delete(
            new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId, roleId)
        );
        
        // 保存新的关联
        if (menuIds != null && !menuIds.isEmpty()) {
            List<SysRoleMenu> roleMenus = menuIds.stream()
                .map(menuId -> {
                    SysRoleMenu roleMenu = new SysRoleMenu();
                    roleMenu.setRoleId(roleId);
                    roleMenu.setMenuId(menuId);
                    return roleMenu;
                })
                .collect(Collectors.toList());
                
            for (SysRoleMenu roleMenu : roleMenus) {
                roleMenuMapper.insert(roleMenu);
            }
        }
    }

    @Override
    public boolean hasChildren(Long menuId) {
        Integer count = baseMapper.selectCount(
            new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getParentId, menuId)
        );
        return count > 0;
    }

    @Override
    public List<SysMenu> getMenuOptions() {
        return baseMapper.selectList(
            new LambdaQueryWrapper<SysMenu>()
                .orderByAsc(SysMenu::getSort)
        );
    }

    @Override
    public boolean isMenuUsed(Long menuId) {
        // 检查是否被角色使用
        Integer count = roleMenuMapper.selectCount(
            new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getMenuId, menuId)
        );
        return count > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addMenu(SysMenu menu) {
        // 检查菜单编码是否重复
        Integer count = menuMapper.selectCount(
            new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getCode, menu.getCode())
        );
        if (count > 0) {
            throw new BusinessException("菜单编码已存在");
        }
        
        menuMapper.insert(menu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMenu(SysMenu menu) {
        // 检查菜单编码是否重复
        Integer count = menuMapper.selectCount(
            new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getCode, menu.getCode())
                .ne(SysMenu::getId, menu.getId())
        );
        if (count > 0) {
            throw new BusinessException("菜单编码已存在");
        }
        
        menuMapper.updateById(menu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMenu(Long id) {
        // 检查是否有子菜单
        Integer count = menuMapper.selectCount(
            new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getParentId, id)
        );
        if (count > 0) {
            throw new BusinessException("该菜单下存在子菜单，无法删除");
        }
        
        menuMapper.deleteById(id);
    }
} 